package com.djs.djsdmsplayer;

import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.extractor.Extractor;
import com.google.android.exoplayer2.extractor.ExtractorInput;
import com.google.android.exoplayer2.extractor.ExtractorOutput;
import com.google.android.exoplayer2.extractor.PositionHolder;
import com.google.android.exoplayer2.extractor.TrackOutput;
import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.ParsableByteArray;

import java.io.IOException;

public class DmsExtractor implements Extractor {
    private static final int MAX_FRAME_SIZE = 4 * 1024 * 1024; // 4MB
    
    private final DmsPlayer dmsPlayer;
    private ExtractorOutput output;
    private TrackOutput trackOutput;
    private long durationUs;
    private float frameRate;
    private long currentTimeUs = 0;
    private boolean hasOutputFormat = false;
    
    private final ParsableByteArray sampleData = new ParsableByteArray(MAX_FRAME_SIZE);
    
    public DmsExtractor(DmsPlayer player) {
        this.dmsPlayer = player;
        this.durationUs = player.getDuration();
        this.frameRate = player.getFrameRate();
    }
    
    @Override
    public boolean sniff(ExtractorInput input) throws IOException {
        return true; // We always handle DMS content
    }
    
    @Override
    public void init(ExtractorOutput output) {
        this.output = output;
        this.trackOutput = output.track(0, C.TRACK_TYPE_VIDEO);
        output.endTracks();
    }
    
    @Override
    public int read(ExtractorInput input, PositionHolder seekPosition) throws IOException {
        if (!hasOutputFormat) {
            setupTrackFormat();
            hasOutputFormat = true;
        }
        
        // Read a frame from DmsDataSource
        int bytesRead = input.read(sampleData.getData(), 0, MAX_FRAME_SIZE);
        if (bytesRead == C.RESULT_END_OF_INPUT) {
            return RESULT_END_OF_INPUT;
        }
        
        if (bytesRead > 0) {
            sampleData.setPosition(0);
            sampleData.setLimit(bytesRead);
            
            // Output the sample
            trackOutput.sampleData(sampleData, bytesRead);
            trackOutput.sampleMetadata(
                currentTimeUs, 
                C.BUFFER_FLAG_KEY_FRAME, 
                bytesRead, 
                0, 
                null
            );
            
            // Calculate next frame time
            currentTimeUs += (long)(1000000 / frameRate);
        }
        
        return bytesRead > 0 ? RESULT_CONTINUE : RESULT_END_OF_INPUT;
    }
    
    @Override
    public void seek(long position, long timeUs) {
        currentTimeUs = timeUs;
        dmsPlayer.seekTo(timeUs);
    }
    
    @Override
    public void release() {
        // Cleanup resources
    }
    
    private void setupTrackFormat() {
        // Create a format for JPEG2000 video
        Format format = Format.createVideoSampleFormat(
            null, // trackId
            MimeTypes.VIDEO_RAW, // Use RAW video type
            null, // codecs
            Format.NO_VALUE, // bitrate
            Format.NO_VALUE, // maxInputSize
            1920, // width (adjust based on actual content)
            1080, // height (adjust based on actual content)
            frameRate, // frameRate
            null, // initializationData
            Format.NO_VALUE, // rotationDegrees
            Format.NO_VALUE, // pixelWidthHeightRatio
            Format.NO_VALUE, // projectionData
            Format.NO_VALUE, // stereoMode
            Format.NO_VALUE, // colorInfo
            null, // sampleMimeType
            Format.OFFSET_SAMPLE_RELATIVE // offset
        );
        
        trackOutput.format(format);
    }
}